// 动效对象
var msrAni = {
  elem: ".anima-block",
  ab: "",
  line: "",
  cube: "",
  unfoldSpeed: 360,
  twinkleSpeed: 42,
  twinkleCount: 4,
  minOpa: .1,
  maxOpa: .7,
  width: "",
  height: "",
  src: "",
  engine: function (opt) {
    $(".anima-block").html(`<div class="wrap">
<div class="line">
<div></div>
<div></div>
</div>
<div class="line">
<div></div>
<div></div>
</div>
</div>`)
    this.width = opt.width;
    this.height = opt.height;
    this.src = opt.src;
    // if has new value, then replace default value. else use default value.
    if (opt.elem) this.elem = opt.elem;
    if (opt.unfoldSpeed) this.unfoldSpeed = opt.unfoldSpeed;
    if (opt.twinkleSpeed) this.twinkleSpeed = opt.twinkleSpeed;
    if (opt.twinkleCount) this.twinkleCount = opt.twinkleCount;
    if (opt.minOpa) this.minOpa = opt.minOpa;
    if (opt.maxOpa) this.maxOpa = opt.maxOpa;
    if (!this.ab) this.ab = this.elem + " .wrap";
    if (!this.line) this.line = this.elem + " .wrap .line";
    if (!this.cube) this.cube = this.elem + " .wrap .line div";
    if (!opt.timeout) opt.timeout = 0;
    this.debug()
    this.iv();
    setTimeout(function () {
      this.init();
    }.bind(this), opt.timeout)
  },
  init: function (t) {
    if (t && this.window) that = t;
    else that = this;
    that.iv();
    that.twinkle();
    that.fn();
  },
  iv: function () {
    $(this.ab).css({
      backgroundImage: 'url("' + this.src + '")',
      height: "1px" // $(this.cube).height()
    });
    $(this.elem).css({
      height: this.height
    });
    $(this.line).css({
      width: "1px" // $(this.cube).width()
    });
  },
  twinkle: function () {
    $(this.cube).animate({
      opacity: this.maxOpa
    }, this.twinkleSpeed, "linear");
    for (var i = 0; i < this.twinkleCount; i++) {
      $(this.cube).animate({
        opacity: this.minOpa
      }, this.twinkleSpeed, "linear");
      $(this.cube).animate({
        opacity: this.maxOpa
      }, this.twinkleSpeed, "linear");
    }
  },
  fn: function () {
    $(this.line).animate({
      width: this.width
    }, this.unfoldSpeed, "swing", function () {
      setTimeout(function () {
        $(this.ab).animate({
          height: this.height
        }, this.unfoldSpeed, "swing")
      }.bind(this), 120)
      return false
    }.bind(this))
  },
  clear: function (f) {
    $(this.elem).attr("style", "");
    $(this.ab).attr("style", "");
    $(this.cube).attr("style", "");
    if (f) f(this);
  },
  again: function () {
    this.clear(this.init);
  },
  debug: function () {
    console.groupCollapsed("all options")
    console.log("elem:", this.elem)
    console.log("unfoldSpeed:", this.unfoldSpeed)
    console.log("twinkleSpeed:", this.twinkleSpeed)
    console.log("twinkleCount:", this.twinkleCount)
    console.log("minOpa:", this.minOpa)
    console.log("maxOpa:", this.maxOpa)
    console.log("width:", this.width)
    console.log("height:", this.height)
    console.log("src:", this.src)
    console.groupEnd()
  }
}

// 乱序码文
var garbled = {
  id: 0,
  strArr: [],
  finish: false,
  // 配置
  opt: {
    fakeElem: "span",
    count: 5, // 最大为10
    time: 42,
    stepTime: 8,
    placeholder: "_"
  },
  // 字典
  lib: {
    num: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    eng: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    ],
    zhcn: ['ㄋ', '〩', '𠃌', '巜', '々', '〤', '彳', '忄', '氵', '阝', '灬', '冫', '卩', '刂', '讠', '扌', '亻', '厃', '⺁', '𠘨', '⺄', '广', '疒', '饣', '钅', '礻',
      '衤', '辶', '牜', '釒', '飠', '⺪', '⻊', '糹', '⺝', '丩', '丬', '犭', '纟', '廴', '攵', '夊', '皿', '臼', '虍', '勹', '尢', '廾', '歺', '夬', '氺', '丂', '爫',
      '癶', '耂', '⺻', '⺮', '⺳', '⺶', '⺷', '⺈', '龵', '彐', '⺋', '罒', '覀', '⻗', '亠', '宀', '冖', '艹', '⺌', '丷', '⺧', '亇', '彡', '𠄌'
    ],
    sign: ["'", '"', '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', ']', '{', '}', ';', ':', ',', '.', '/', '<', '>', '?',
      '！', '·', '￥', '…', '*', '（', '）', '—', '《', '》', '；', '：', '【', '】', '‘', '’', '“', '”', '？', '、', '|', '\\', '，', '。'
    ]
  },
  // 正则库
  reg: {
    num: new RegExp("[0-9]"),
    eng: new RegExp("[a-zA-Z]"),
    zhcn: new RegExp("[\u4e00-\u9fa5]")
  },
  // 初始化
  load: function (opts) {
    // 元素校验
    var elem;
    if (opts.elem) elem = opts.elem;
    else if (typeof opts === 'string') {
      elem = opts;
      opts = {
        elem
      }
    } else console.warn("elem is Err.");
    if (!$(elem).hasClass("ooo")) $(elem).addClass("ooo")
    if ($(elem).length > 1) {
      console.warn(`Warn: There are ${$(elem).length} elements of class "${elem}" , please check it out and do something.`)
      // elem = elem + ":eq(0)" // 只获取第一个元素的内容
      // 合并元素
      for (var i = 1; i < $(elem).length; i++) {
        var me = $(elem + ":eq(0)").text();
        var it = $(elem + ":eq(" + i + ")").text();
        $(elem + ":eq(0)").text(me + it)
      }
      $(elem).not(elem + ":eq(0)").remove();
    }

    // 参数校验
    if (!opts.placeholder) opts.placeholder = this.opt.placeholder;
    if (!opts.fakeElem) opts.fakeElem = this.opt.fakeElem;
    if (!opts.count) opts.count = this.opt.count;
    if (!opts.stepTime) opts.stepTime = this.opt.stepTime;
    if (!opts.time) opts.time = this.opt.time;
    if (!opts.timeout) opts.timeout = 0;

    // 变量声明
    var arr = $(elem).text().split(''),
      newArr = [],
      nodeStr = "";

    setTimeout(function () {
      // 前置对象生成
      arr.forEach((item, index) => {
        var type, ooo = [opts.placeholder];
        // console.log(item, index)
        nodeStr += "<" + opts.fakeElem + ">" + item + "</" + opts.fakeElem + ">"; // 新的元素节点
        if (item != ' ') {
          // 正则匹配格式
          if (this.reg.num.test(item)) type = 'num';
          else if (this.reg.eng.test(item)) type = 'eng';
          else if (this.reg.zhcn.test(item)) type = 'zhcn';
          else type = 'sign';
          // 生成乱序列表
          var a = [...this.lib[type]];
          for (var i = 0; i < opts.count; i++) {
            var b = this.randomList(a, true);
            ooo.push(b.value);
            a = b.filter;
          }
        }
        // 合成新对象: char
        newArr.push({
          elem: elem + " " + opts.fakeElem + ":eq(" + index + ")",
          index,
          val: item,
          type,
          ooo,
          t: 0
        })
      });
      $(elem).html(nodeStr); // 整合元素
      this.strArr.push({
        id: this.id,
        elem,
        opts,
        char: newArr,
        t: 0
      })
      $(elem).css("opacity", "1");
      this.controller(this.id); // 走控制器
      this.id++;
    }.bind(this), opts.timeout)
  },
  // 主控制器
  controller: function (id) {
    this.timeoutFn(id, 0); // 走延时器
  },
  // 延时器分离控制每个字符出现的时间
  timeoutFn: function (id) {
    var tsa = this.strArr[id];
    if (!tsa.char[tsa.t]) return false;
    setTimeout(function () {
      $(tsa.char[tsa.t].elem).css("opacity", "1");
      if (tsa.t != tsa.char[tsa.t].index) return true;
      if (tsa.t < tsa.char.length) {
        this.replacer(id, tsa.char[tsa.t]);
        tsa.t++;
        this.timeoutFn(id); // 自循环
      } else return false
    }.bind(this), tsa.opts.time)
  },
  // 字符跳动替换器
  replacer: function (id, v) {
    var opts = this.strArr[id].opts;
    if (v.t < opts.count - 1) {
      $(v.elem).text(v.ooo[v.t]);
      v.t++;
      setTimeout(function () {
        this.replacer(id, v); // 自循环
      }.bind(this), opts.time + (opts.stepTime * v.t))
    } else {
      $(v.elem).text(v.val); // 次数已达要求，更换为正常的文字
      return false
    }
  },
  randomList: function (arr, f, r) {
    var i = Math.floor(((Math.random() * 10) % arr.length) + 1)
    var returnObj = {
      value: (arr[i] === 0 ? 0 : arr[i]),
      index: i,
    }
    if (f) {
      var arr1 = Object.assign([], arr)
      arr1.splice(i, 1)
      returnObj.filter = arr1
    }
    if (r != undefined) {
      var arr2 = Object.assign([], arr)
      arr2.splice(i, 1, r)
      returnObj.replace = arr2
    }
    return returnObj
  }
}